package com.gong.gongcloudpicture1.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gong.gongcloudpicture1.common.BaseResponse;
import com.gong.gongcloudpicture1.constant.UserConstant;
import com.gong.gongcloudpicture1.exception.BusinessException;
import com.gong.gongcloudpicture1.exception.ErrorCode;
import com.gong.gongcloudpicture1.model.dto.user.*;
import com.gong.gongcloudpicture1.model.entity.user.User;
import com.gong.gongcloudpicture1.model.enums.UserRoleEnum;
import com.gong.gongcloudpicture1.model.vo.user.UserLoginVo;
import com.gong.gongcloudpicture1.model.vo.user.UserVO;
import com.gong.gongcloudpicture1.service.PictureService;
import com.gong.gongcloudpicture1.service.UserService;
import com.gong.gongcloudpicture1.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author g1783
 * @description 针对表【user(用户)】的数据库操作Service实现
 * @createDate 2025-05-23 20:50:37
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {


    private static final String YES = "1";
    private static final String NO = "0";


    @Resource
    private UserMapper userMapper;


    /**
     * 用户注册
     *
     * @param userRegisterRequest
     * @return
     */
    @Override
    public BaseResponse<Long> userRegister(UserRegisterRequest userRegisterRequest) {
        //1 校验参数
        if (StrUtil.hasBlank(userRegisterRequest.getUserAccount(), userRegisterRequest.getUserPassword(), userRegisterRequest.getUserAccount())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "参数异常");
        }
        if (userRegisterRequest.getUserAccount().length() < 4) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户账号长度不能小于4");
        }
        if (userRegisterRequest.getUserPassword().length() < 8 || userRegisterRequest.getCheckPassword().length() < 8) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户密码长度不能小于8");
        }
        if (!userRegisterRequest.getUserPassword().equals(userRegisterRequest.getCheckPassword())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "第二次密码不一致");
        }
        //2 判断数据库是否有重复数据
        Long count = userMapper.selectCount(
                new LambdaQueryWrapper<User>()
                        .eq(User::getUserAccount, userRegisterRequest.getUserAccount())
                        .eq(User::getIsDel, NO)
        );
        if (count >= 1) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "当前用户已存在");
        }
        //3 密码需要加密 如MD5加密 + 盐(随机的字符串, 需要存储到数据库)
        //3.1 创建盐, 随机字符串 + 时间戳 + 随机字符串
        String salt = UUID.randomUUID().toString().substring(0, 6) + String.valueOf(new Date().getTime()).substring(6, 12) + UUID.randomUUID().toString().substring(0, 6);
        //新密码
        String password = encryptionPassword(userRegisterRequest.getUserPassword(), salt);
        //4 插入到数据库
        User newUser = new User();
        newUser.setUserAccount(userRegisterRequest.getUserAccount());
        newUser.setUserPassword(password);
        newUser.setSalt(salt);
        newUser.setUserRole(UserRoleEnum.USER.getValue());
        String userName = "新用户" + new Date().getTime();
        newUser.setUserName(userName);
        try {
            userMapper.insert(newUser);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户注册失败, 数据库错误!");
        }
        return BaseResponse.success(newUser.getId());
    }


    /**
     * 加密密码
     * 盐 + 密码 通过 MD5加密方式加密
     *
     * @param userPassword
     * @param salt
     * @return
     */
    private String encryptionPassword(String userPassword, String salt) {
        String password = salt + userPassword;
        return DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8));
    }


    /**
     * 用户登录, 登录成功后返回脱敏信息
     *
     * @param userLoginRequest
     * @param request
     * @return
     */
    @Override
    public BaseResponse<UserLoginVo> login(UserLoginRequest userLoginRequest, HttpServletRequest request) {
        //1 校验登录的参数
        if (StrUtil.hasBlank(userLoginRequest.getUserAccount(), userLoginRequest.getUserPassword(), userLoginRequest.getUserAccount())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "参数异常");
        }
        if (userLoginRequest.getUserAccount().length() < 4) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户账号长度不能小于4");
        }
        if (userLoginRequest.getUserPassword().length() < 8) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户密码长度不能小于8");
        }
        //2 判断用户是否存在
        User user = userMapper.selectOne(
                new LambdaQueryWrapper<User>()
                        .eq(User::getUserAccount, userLoginRequest.getUserAccount())
                        .eq(User::getIsDel, NO)
        );
        if (user == null) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "当前登录账户不存在");
        }
        //3 结合盐 + 传参密码 与 盐 + 用户密码 加密进行比对
        String requestPassword = encryptionPassword(userLoginRequest.getUserPassword(), user.getSalt());
        if (!requestPassword.equals(user.getUserPassword())) {
            log.info("user login failed, userAccount cannot match userPassword");
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户登录密码错误");
        }
        //4 保存登录状态
        //这个sessionId是由前端传进来的, 不同的浏览器或者不同的用户的都会请求进来的都是唯一sessionId, 然后将登录信息保存在这个session的独立空间中
        //告诉浏览器, 当前登录的用户是谁
        request.getSession().setAttribute(UserConstant.USER_LOGIN_STATE, user); //
        //获取或创建 Session（自动存入 Redis）
        HttpSession session = request.getSession(true);
        //返回脱敏信息
        UserLoginVo userLoginVo = new UserLoginVo();
        BeanUtils.copyProperties(user, userLoginVo);
        return BaseResponse.success(userLoginVo);
    }


    /**
     * 获取当前登录用户
     *
     * @param request
     * @return
     */
    @Override
    public BaseResponse<UserLoginVo> getLogInUser(HttpServletRequest request) {
        //从会话中, 获取当前的登录人
        User currentUser = (User) request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
        if (currentUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        //因为登录用户最开始就已经存储在缓存中, 如果用户修改了个人信息, 没有从更新缓存可能会导致信息不一致的原因
        //这里需要在查一遍给缓存覆盖掉(如果不追求性能, 可以直接查数据库)
        currentUser = userMapper.selectOne(
                new LambdaQueryWrapper<User>()
                        .eq(User::getId, currentUser.getId())
                        .eq(User::getIsDel, NO)
        );
        if (currentUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        return BaseResponse.success(getInfoUser(currentUser));
    }



    @Override
    public User getLogInUser2(HttpServletRequest request) {
        //从会话中, 获取当前的登录人
        User currentUser = (User) request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
        if (currentUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        //因为登录用户最开始就已经存储在缓存中, 如果用户修改了个人信息, 没有从更新缓存可能会导致信息不一致的原因
        //这里需要在查一遍给缓存覆盖掉(如果不追求性能, 可以直接查数据库)
        currentUser = userMapper.selectOne(
                new LambdaQueryWrapper<User>()
                        .eq(User::getId, currentUser.getId())
                        .eq(User::getIsDel, NO)
        );
        if (currentUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        return currentUser;
    }


    /**
     * 返回登录用户脱敏信息
     *
     * @return
     */
    public UserLoginVo getInfoUser(User user) {
        UserLoginVo userLoginVo = new UserLoginVo();
        BeanUtils.copyProperties(user, userLoginVo);
        return userLoginVo;
    }


    /**
     * 用户注销
     *
     * @param request
     * @return
     */
    @Override
    public BaseResponse<Boolean> logout(HttpServletRequest request) {
        //从会话中, 获取当前的登录人
        User currentUser = (User) request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
        if (currentUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        //移除登录态
        request.getSession().removeAttribute(UserConstant.USER_LOGIN_STATE);
        //直接删除整个session, 同时redis中缓存的session也会删除
        //HttpSession session = request.getSession();
        //session.invalidate();
        return BaseResponse.success(true);
    }


    /**
     * 返回脱敏用户信息
     *
     * @param user
     * @return
     */
    public UserVO getUserVo(User user) {
        if (user == null) {
            return null;
        }
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }


    /**
     * 批量返回脱敏用户信息
     *
     * @param userList
     * @return
     */
    public List<UserVO> getUserVoList(List<User> userList) {
        if (CollectionUtil.isEmpty(userList)) {
            return new ArrayList<>();
        }
        return userList.stream()
                .map(this::getUserVo)
                .collect(Collectors.toList());
    }


    /**
     * 获取分页查询用户条件
     * @param userQueryRequest
     * @return
     */
    @Override
    public QueryWrapper<User> getQueryWrapper(UserQueryRequest userQueryRequest) {
        if (userQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(userQueryRequest.getUserName())) {
            queryWrapper.like("user_name", userQueryRequest.getUserName());
        }
        if (StringUtils.isNotBlank(userQueryRequest.getUserAccount())) {
            queryWrapper.like("user_account", userQueryRequest.getUserAccount());
        }
        if (StringUtils.isNotBlank(userQueryRequest.getUserProfile())) {
            queryWrapper.like("user_profile", userQueryRequest.getUserProfile());
        }
        if (StringUtils.isNotBlank(userQueryRequest.getUserRole())) {
            queryWrapper.eq("user_role", userQueryRequest.getUserRole());
        }
        String sortOrder = userQueryRequest.getSortOrder();
        String sortField = userQueryRequest.getSortField();
        //设置排序字段 默认正序
        queryWrapper.orderBy(StringUtils.isNotBlank(sortField), sortOrder.equals("ascend"), sortField);
        return queryWrapper;
    }


    /**
     * 创建用户
     * @param userAddRequest
     * @return
     */
    @Override
    public BaseResponse<Long> addUser(UserAddRequest userAddRequest) {
        User user = new User();
        BeanUtils.copyProperties(userAddRequest, user);
        final String DEFAULT_PASSWORD = "123456";
        final String DEFAULT_SALT = "ytk";
        String password = encryptionPassword(DEFAULT_PASSWORD, DEFAULT_SALT);
        user.setUserPassword(password);
        //插入数据库
        userMapper.insert(user);
        return BaseResponse.success(user.getId());
    }


    /**
     * 通过id获取用户(管理员可操作)
     *
     * @param id
     * @return
     */
    @Override
    public BaseResponse<User> getUserById(Long id) {
        User user = userMapper.selectOne(
                new LambdaQueryWrapper<User>()
                        .eq(User::getId, id)
                        .eq(User::getIsDel, NO)
        );
        if (user == null) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR.getCode(), "数据不存在");
        }
        return BaseResponse.success(user);
    }


    /**
     * 更新用户
     *
     * @param userUpdateRequest
     * @return
     */
    @Override
    public BaseResponse<Boolean> updateUser(UserUpdateRequest userUpdateRequest) {
        if (userUpdateRequest.getId() == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        User user = new User();
        BeanUtils.copyProperties(userUpdateRequest, user);
        userMapper.updateById(user);
        return BaseResponse.success(true);
    }


    /**
     * 用户分页
     *
     * @param userQueryRequest
     * @return
     */
    @Override
    public BaseResponse<Page<UserVO>> listUserVoByPage(UserQueryRequest userQueryRequest) {
        QueryWrapper<User> queryWrapper = getQueryWrapper(userQueryRequest);
        Page<User> userPage = userMapper.selectPage(new Page<>(userQueryRequest.getCurrent(), userQueryRequest.getPageSize()), queryWrapper);
        Page<UserVO> userVOPage = new Page<>(userPage.getCurrent(), userPage.getSize());
        List<UserVO> userVoList = getUserVoList(userPage.getRecords());
        userVOPage.setRecords(userVoList);
        userVOPage.setTotal(userPage.getTotal());
        return BaseResponse.success(userVOPage);
    }


    /**
     * 判断是否是管理员
     * @param user
     * @return
     */
    @Override
    public boolean isAdmin(User user) {
        return user != null && UserRoleEnum.ADMIN.getValue().equals(user.getUserRole());
    }
    @Override
    public boolean isAdmin(UserLoginVo user) {
        return user != null && UserRoleEnum.ADMIN.getValue().equals(user.getUserRole());
    }




}




